package model.info;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.net.URL;
import java.util.ArrayList;
import java.util.Vector;

public class Coordinate implements Serializable {

    private double latitude = 0;
    private double longitude = 0;

    public Coordinate() {
    }

    public Coordinate(double latitude, double longitude) throws CoordinateRangeException  {
        
        this.setLatitude(latitude);
        this.setLongitude(longitude);
    }

    public Coordinate(String address) throws IOException {
    	
        getStringCoordinate(address);
    }
  
    public double getLatitude() {
        return latitude;
    }

    public void setLatitude(double val) throws CoordinateRangeException {
        if(val < -90 || val > 90)
            throw new CoordinateRangeException("Coordinates out of range");
        else
            this.latitude = val;
    }

    public double getLongitude() {
        return longitude;
    }

    public void setLongitude(double val) throws CoordinateRangeException {
        if(val < -180 || val > 180)
            throw new CoordinateRangeException("Coordinates out of range");
        else
            this.longitude = val;
    }

    public void setValuesForAddress(String address) throws IOException {
    	
        getStringCoordinate(address);
    }
    
    public double getDistance(Coordinate cor) {
        
        double a=this.getLatitude()-cor.getLatitude();
        double b=this.getLongitude()-cor.getLongitude();
        
        return Math.hypot(a, b)*111.195*1E6; 
    }
    
    public static double getDistance(Coordinate corA,Coordinate corB) {
    	
        double a=corA.getLatitude()-corB.getLatitude();
        double b=corA.getLongitude()-corB.getLongitude();
        
        return Math.hypot(a, b)*111.195*1E6;
    }
    
    public static double getDistance(ArrayList<Coordinate> lista) {
    	
        double counter = 0;
        boolean first = true;
        Coordinate one = null;
        for(Coordinate coor : lista) {
            if(first) {
                one = coor;
                first = false;
            }
            else {
                counter += one.getDistance(coor);
                one = coor;
            }
        }
        return counter;
    }
   
    private void getStringCoordinate(String address) throws IOException {
    	
        URL url = new URL(getGeoCoordinateURL(address));
        InputStream stream = url.openStream();
        BufferedReader buffer = new BufferedReader(new InputStreamReader(stream));
        String web = buffer.readLine();

        String coordenadas[] = Split(web, ',');
        this.latitude=Double.parseDouble(coordenadas[2]);
        this.longitude=Double.parseDouble(coordenadas[3]);
    }

    private String getGeoCoordinateURL(String address) {
    	
        return "http://maps.google.es/maps/geo?q=" + UrlEncode(address) +
                "&output=csv";
    }

    private String UrlEncode(String url) {
    	
        StringBuffer buffer = new StringBuffer();
        char word;
        for (int i = 0; i < url.length(); i++) {
            word = url.charAt(i);
            if ((word >= '0' && word <= '9') ||
                    (word >= 'A' && word <= 'Z') ||
                    (word >= 'a' && word <= 'z'))
                buffer.append(word);
            else
                buffer.append("%").append(Integer.toHexString((int) url.charAt(i)));
        }
        return buffer.toString();
    }

    private String[] Split(String text, int character) {
    	
        Vector<String> vector = new Vector<String>();
        int current = 0;
        int prior = 0;

        while ((current = text.indexOf(character, prior)) >= 0) {
            vector.addElement(text.substring(prior, current));
            prior = current + 1;
        }

        vector.addElement(text.substring(prior));
        String[] split = new String[vector.size()];
        vector.copyInto(split);

        return split;
    }    
    
    public String toString() {
    	
    	return latitude+","+longitude;
    }
}